﻿using System;
using System.Collections.Generic;
using System.Text;
using FlickrMe.Config;
using FlickrMe.Auth;
using FlickrMe.Upload;
using FlickrMe.browser;
using System.Windows.Forms;
using FlickrNet;
using FlicrkrMe.Upload;
using System.IO;
using System.Threading;

namespace FlickrMe
{
    class FlickrMe
    {

        private Flickr flickr;
        private FlickrConfig config;
        private FlickrAuthenticationManager authMan;
        private FlickrUpload upload;
        private ConfigManager configMan;

        Thread uploadThread;

        /**
         * Create a new FlickrMe instance with config manager type
         */
        public FlickrMe(int type)
        {
            init(type);
        }

        private void init(int type)
        {
            LoadConfig(type);
            flickr = new Flickr(config.ApiKey, config.SharedSecret);
            authMan = new FlickrAuthenticationManager(flickr);
        }

        /*
         * Prompts user to select image files and then uploads them.
         */
        public void doUpload()
        {
            Browse b = new Browse();
            String[] filenames = b.getMultiBrowsePath();
            doUpload(filenames);
        }

        /*
         * Upload files whose names are in filenames. filenames can contain file, folder and .lnk names.
         * .lnk names will be resolved, and folders read recursevley.
         */
        public void doUpload(String[] filenames)
        {
            // Build up list of filenames to be uploaded
            filenames = Utility.getImageFilenamesFromFolders(filenames);

            
            if (filenames.Length == 0)
            {
                // Generaly filenames will be empty be due to selecting a folder with no image files
                // or selecting a file that is not an image.
                return;
            }
            
            try
            {
                if (!authMan.IsValidAuthToken(config.AuthToken))
                {
                    if (DoUserAuthentication())
                    {
                        config.AuthToken = authMan.getAuthToken();
                        saveConfig(config);
                    }
                    else
                    {
                        return;
                    }

                }
               
            }
            catch (AuthenticationException ex)
            {
                MessageBox.Show("Unable to connect to Internet.\nPlease Check your connection.", 
                                    "Error", MessageBoxButtons.OK);
                return;
            }

            flickr.AuthToken = config.AuthToken;

            // Prepare to upload.
            upload = new FlickrUpload(flickr);
            upload.Filenames = filenames;

            UploadDialog ud = new UploadDialog();
            

            // Add Event handlers that monitor upload progress
            upload.UploadStartEvent += new UploadStart(ud.upload_UploadStartEvent);
            upload.FileUploadStartEvent += new FileUploadStart(ud.upload_FileUploadStartEvent);
            upload.FileUploadCompleteEvent += new FileUploadComplete(ud.upload_FileUploadCompleteEvent);
            upload.FileUploadProgressEvent += new FileUploadProgress(ud.upload_FileUploadProgressEvent);
            upload.UploadCompleteEvent += new UploadComplete(ud.upload_UploadCompleteEvent);

            // Add event handler for when dialog is shown so we can kick off the discovery.
            ud.Shown += new EventHandler(ud_Shown);

            // Add event handler for when dialog is closed so we can cancel the uploading.
            ud.FormClosed += new FormClosedEventHandler(UploadDialog_FormClosed);

            ud.ShowDialog();
        }

        /**
         * uploads files. This method is called from a new thread.
         */
        private void uploadFiles(Object upload)
        {
            try
            {
                ((FlickrUpload)upload).uploadFiles();
            }
            catch (UploadException ex)
            {
                MessageBox.Show("Failed to upload file.\nThere may be a problem with your connection.", "Error", MessageBoxButtons.OK);
            }
            
        }

        /*
         * Gets Config from the Config Manager.
         *
         */
        private void LoadConfig(int type)
        {
            configMan = ConfigManager.getInstance(type);
            config = configMan.getConfig();
        }

        /*
         * Saves the current configuration via the Config Manager
         */
        private void saveConfig(FlickrConfig config)
        {
            configMan.saveConfig(config);
        }

        /*
         * Prompts the user to authenticate the application.
         * Opens a browser window and directs to Flickr login screen.
         * 
         * This code is a bit shitty and could do with a re-work.
         * 
         * @Returns true if the authentication process was completed. False otherwise
         */
        public bool DoUserAuthentication()
        {
            Boolean completed = false;

            // Shows the prompt.
            AuthDialog d = new AuthDialog();

            if (d.ShowDialog() == DialogResult.OK)
            {
                // The url for Flickr Authentication page
                String url = authMan.getAuthUrl();

                //TODO: rather than pass authman add event hander for navigated.
                FlickrBrowser b = new FlickrBrowser(authMan, url);

                if (b.ShowDialog() == DialogResult.OK)
                {
                    completed = true;
                }
            }
            return completed;
        }

    

        private void UploadDialog_FormClosed(Object obj, EventArgs args)
        {
            // As we are Killing the upload thread immediately
            // There is no need to unregister event handlers
            uploadThread.Abort();
        }

        // Upload is started after dialog is show to provent timing issues
        // with upload events being fired before dialog is ready.
        private void ud_Shown(Object obj, EventArgs args)
        {
            uploadThread = new Thread(uploadFiles);
            uploadThread.Start(upload);
        }
    }
}
